package com.example.product.shiro;

import com.example.api.entity.SysPermission;
import com.example.api.entity.SysRole;
import com.example.api.entity.SysSystem;
import com.example.api.entity.SysUser;
import com.example.api.util.SysCode;
import com.example.product.exception.SysUsreNotLoginAPPException;
import com.example.product.exception.SystemNotExistException;
import com.example.product.service.SysPermissionService;
import com.example.product.service.SysRoleService;
import com.example.product.service.SysSystemService;
import com.example.product.service.SysUserService;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;

public class MyShiroRealm extends AuthorizingRealm {

    private Logger logger = LoggerFactory.getLogger(MyShiroRealm.class);
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysPermissionService sysPermissionService;
    @Autowired
    private SysSystemService systemService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        logger.info("####################开始配置权限####################");
        SysUser user = (SysUser) principalCollection.getPrimaryPrincipal();
        if (user != null) {
            //权限信息对象info,用来存放查出的用户的所有的角色（role）及权限（permission）
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            List<String> roleStrlist = new ArrayList<String>();//用户的角色集合
            List<String> perminsStrlist = new ArrayList<String>();//用户的菜单权限集合
            for (SysRole role : user.getRoleList()) {
                roleStrlist.add(role.getRoleName());
            }
            for (SysPermission permission : user.getPermissList()) {
                perminsStrlist.add(permission.getUrl());
            }
            //用户的角色集合
            authorizationInfo.addRoles(roleStrlist);
            //用户的菜单按钮权限集合
            //公共主页
            perminsStrlist.add("manage/main");
            authorizationInfo.addStringPermissions(perminsStrlist);
            return authorizationInfo;
        }
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        logger.info("####################身份认证####################");
        String userStr = (String) authenticationToken.getPrincipal();
        String userName = userStr.split(",")[0];
        String systemId = "0";

        SysUser user = sysUserService.getUserByUserName(userName);

        if(userStr.contains(",")){
            systemId = userStr.split(",")[1];
        }else if(user!=null && user.getUserType().equals(SysCode.USER_TYPE.APP_USER)){
            systemId="";
        }
        SysSystem system=(SysSystem) systemService.findBySystemId(systemId);
        if (user == null) {
            throw new UnknownAccountException(userName+",不是认证系统用户");
        }else if(user.getLocked().equals(SysCode.LOGIN.LOCKED)){
            throw new LockedAccountException(userName+",账户已锁定请联系管理员");
        }else if(user.getUserType().equals("0")&& systemId.equals("0")){
            user.setSystemId(systemId);
        }else if(user.getUserType().equals(SysCode.USER_TYPE.CERT_USER)&& !systemId.equals("0")){
            throw new SysUsreNotLoginAPPException("系统用户不能登陆应用系统");
        }else if(user.getUserType().equals(SysCode.USER_TYPE.APP_USER) && system==null){
            throw new SystemNotExistException("该用户登陆未知的系统");
        }else{
            user.setSystemUrl(system.getUrl());
        }
        user.setSystemId(systemId);
        //认证系统用户
        List<SysRole> roleList = sysRoleService.findRoleByUserId(user.getUserId(),systemId);
        user.setRoleList(roleList);//获取用户角色
        List<SysPermission> list=sysPermissionService.getUserPermission(user.getUserId(),systemId);
        SysPermission permis=new SysPermission();
        //公共主页
        permis.setUrl("manage/main");
        list.add(permis);
        user.setPermissList(list);//获取用户权限

        //HashedCredentialsMatcher.class->doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) 加密方法
        //ShiroConfig.class->hashedCredentialsMatcher() 配置了几次加密,这里就需要几次加密，
        //password加密是对数据库里的密码N次加密，然后与登录token里的密码N次加密后匹配正确则认证通过
        String password= Hex.encodeHexString(DigestUtils.md5(user.getPassword().getBytes()));
        return new SimpleAuthenticationInfo(user, password,getName());
    }
}
